/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#ifndef _INC_AK_QUEUE_
#define	_INC_AK_QUEUE_

#include "ak_types.h"
#include "ak_lock.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 	---------------------------------------------------------------------------
**	We use the traditional NUL-end Bi-Direction Que as for Easier Range Judge :(.
**	Change Back to the Ring Queue.!
**	Only implement the __inline OPs of.
** 	DblList_Add()
** 	DblList_Get()
**	DblList_Del()
** 	DblList_Cat()
** 	the Count of the List is Long & on X86-64 is 64bit/8Bytes.
*/
typedef struct _t_bnode{ 
	struct _t_bnode	*next;
	struct _t_bnode	*prev; 
}_t_bnode; 

typedef struct _t_blist{ 
	union{
	struct _t_bnode *head;		/* Head of the List */
	struct _t_bnode	*next; 		
	struct _t_blist *nextL;
	};
	union{
	struct _t_bnode *tail;		/* Tail of the List */
	struct _t_bnode	*prev; 		
	struct _t_blist *prevL;
	};
	long		count;
}_t_blist; 

/* Node & List Init, Must be Init to Use! */
#define BNODE_INIT(varDblP) 	\
do{	\
	(varDblP)->next =       	\
	(varDblP)->prev = varDblP;	\
}while(0)

#define BLIST_INIT(vPList) 	\
do{	\
	(vPList)->nextL =       	\
	(vPList)->prevL = (vPList);	\
	(vPList)->count= 0;\
}while(0)


/* 	---------------------------------------------------------------------------
**	Apps are not curraged to call the Above inline functions directly.
** 	The Below Type-Adjust OPs for DblList Marco are recommend to Use. 
*/
#define BLST_BUBBLE2H(pLst, pNode) 		_BList_Bubble2H((_t_blist*)(pLst), (_t_bnode*)(pNode))
#define BLST_BUBBLE2T(pLst, pNode) 		_BList_Bubble2T((_t_blist*)(pLst), (_t_bnode*)(pNode))

#define BLST_ADD2H(pLst, pNode) 		_BList_Add2H((_t_blist*)(pLst), (_t_bnode*)(pNode))
#define BLST_ADD2T(pLst, pNode) 		_BList_Add2T((_t_blist*)(pLst), (_t_bnode*)(pNode))

#define BLST_GET(pLst)       			_BList_Get((_t_blist*)(pLst))
#define BLST_DEL(pLst, pNode) 			_BList_Del((_t_blist*)(pLst), (_t_bnode*)(pNode))

/* We don't implement the GetN __inline */
#define BLST_GETN(pSrc, pDst, num) 		BList_GetN((_t_blist*)(pSrc), (_t_blist*)(pDst), (num))

#define BLST_INSERT(pLst, pRef, pNode) 	_BList_Insert((_t_blist*)(pLst), (_t_bnode*)(pRef), (_t_bnode*)(pNode))
#define BLST_APPEND(pLst, pRef, pNode) 	_BList_Append((_t_blist*)(pLst), (_t_bnode*)(pRef), (_t_bnode*)(pNode))

#define BLST_CAT(pDst, pSrc) 			_BList_Cat(	(_t_blist*)(pDst), (_t_blist*)(pSrc))
#define BLST_JOIN(pDst, pSrc) 			_BList_Join((_t_blist*)(pDst), (_t_blist*)(pSrc))


/* 	---------------------------------------------------------------------------
**	SList:
**	We use an non-count Queue for RB-Tree's Lx-GC.
*/
typedef struct _t_snode{ 
	struct _t_snode	*next;
	struct _t_snode	*prev; 
}_t_snode; 

#define SNODE_ISOLATE(pNode) 		((pNode)->next == pNode)

#define SNODE_INIT(pNode)	\
	do{\
		(pNode)->next = (pNode)->prev = pNode;\
	}while(0)

#define SNODE_ADD2T(pNode1, pNode2) \
	do{\
		(pNode1)->prev->next = (pNode2);\
		(pNode2)->prev 		 = (pNode1)->prev;\
		(pNode1)->prev 		 = (pNode2);\
		(pNode2)->next 		 = (pNode1);\
	}while(0)

#define SNODE_ADD2H(pNode1, pNode2) \
	do{\
		(pNode1)->next->prev = (pNode2);\
		(pNode2)->next 		 = (pNode1)->next;\
		(pNode1)->next 		 = (pNode2);\
		(pNode2)->prev 		 = (pNode1);\
	}while(0)

#define SNODE_DEL(pNode) \
	do{\
		(pNode)->prev->next = (pNode)->next;	\
		(pNode)->next->prev = (pNode)->prev;	\
		(pNode)->next = (pNode)->prev = pNode;	\
	}while(0)



/* Bubble a Node 2 Head. */
static __inline		void		_BList_Bubble2H(_t_blist * pLst, _t_bnode * pNode){
	if(pLst && pNode){
		pNode->prev->next=pNode->next;		pNode->next->prev=pNode->prev;
		/* Add 2 H */
		pNode->prev=(_t_bnode *)pLst; 		pNode->next=pLst->next;
		pLst->next->prev=pNode;				pLst->next=pNode;
	}
	return;
}

/* Bubble a Node 2 Tail. */
static __inline		void		_BList_Bubble2T(_t_blist * pLst, _t_bnode * pNode){
	if(pLst && pNode && (pLst->prev != pNode)){
		pNode->prev->next=pNode->next;		pNode->next->prev=pNode->prev;
		/* Add 2 T */
		pNode->prev=pLst->prev;				pNode->next=(_t_bnode *)pLst;
		pLst->prev->next=pNode;				pLst->prev=pNode;
	}
	return;
}

/* Get a Node From the List's Head. */
static __inline 	_t_bnode*	_BList_Get(_t_blist * pLst){
	_t_bnode * pNode = NULL;
	if(pLst && (pLst->count > 0)){
		pNode=pLst->next;  pLst->next=pNode->next;
		pNode->next->prev=(_t_bnode *)pLst;
		--(pLst->count);
	}
	return pNode;
}

/* Add a Node to the Head of the List. */
static __inline		void		_BList_Add2H(_t_blist * pLst, _t_bnode * pNode){
	if(pLst && pNode){
		pNode->prev=(_t_bnode *)pLst; 	pNode->next=pLst->next;
		pLst->next->prev=pNode;			pLst->next=pNode;
		++(pLst->count);
	}
	return;
}

/* Add a Node to the Tail of the List. */
static __inline		void		_BList_Add2T(_t_blist * pLst, _t_bnode * pNode){
	if(pLst && pNode){
		pNode->prev=pLst->prev;	pNode->next=(_t_bnode *)pLst;
		pLst->prev->next=pNode;	pLst->prev=pNode;
		++(pLst->count);
	}
	return;
}

/* Del a Node From the List. */
static __inline		void		_BList_Del(_t_blist * pLst, _t_bnode * pNode){
	if(pLst && pNode && (pLst->count > 0)){
		pNode->prev->next=pNode->next;	pNode->next->prev=pNode->prev;
		--(pLst->count);
	}
	return;
}

/* Insert a Node to the List. */
static __inline		void		_BList_Insert(_t_blist * pLst, _t_bnode * pRef, _t_bnode * pNode){
	if(pLst && pNode && pRef){
		pNode->prev = pRef->prev;		pNode->next = pRef;
		pRef->prev->next= pNode;		pRef->prev  = pNode;
		++(pLst->count);
	}
	return;
}

/* Append a Node to the List. */
static __inline		void		_BList_Append(_t_blist * pLst, _t_bnode * pRef, _t_bnode * pNode){
	if(pLst && pNode && pRef){
		pNode->next = pRef->next;		pNode->prev = pRef;
		pRef->next->prev = pNode;		pRef->next  = pNode;
		++(pLst->count);
	}
	return;
}

/* Cat a List to the Tail of Other. */
static __inline 	int		_BList_Cat(_t_blist * pDst, _t_blist * pSrc){
	if(pDst && pSrc && (pSrc->count > 0)){
		/* Dst Tail <- Src Head */
		pDst->prev->next = pSrc->next; 
		pSrc->next->prev = pDst->prev; 		
		pSrc->prev->next = (_t_bnode *)pDst;
		pDst->prev 	  	 = pSrc->prev;

		pDst->count += pSrc->count;
		pSrc->next 	= 
		pSrc->prev 	= (_t_bnode *)pSrc; 
		pSrc->count = 0;
		return 0;
	}
	return -1;
}

/* Join a List to the Head of Other. */
static __inline 	int		_BList_Join(_t_blist * pDst, _t_blist * pSrc){
	if(pDst && pSrc && (pSrc->count > 0)){
		/* Src Tail <- Dst Head */
		pDst->next->prev = pSrc->prev;
		pSrc->prev->next = pDst->next;
		pSrc->next->prev = (_t_bnode *)pDst;
		pDst->next 		 = pSrc->next;
		
		pDst->count += pSrc->count; 
		pSrc->next 	= 
		pSrc->prev 	= (_t_bnode *)pSrc; 
		pSrc->count = 0;
		return 0;
	}
	return -1;
}

extern 	int 	BList_GetN(_t_blist * pSrc, _t_blist * pDst, int num);

/* Add support of the Ready-Standby-Idle Queue, With Event Trigger Support */
#define 	_RSI_IDLE		0
#define 	_RSI_STDBY 		1
#define 	_RSI_READY 		2

typedef struct{
	_t_bnode 		node;
	int 			waken;
	int 			state;
}_t_rsiNode;

typedef struct{
	_t_sysCS 	* 	pLock;
	_t_blist 		ready;
	_t_blist 		stdby;
}_t_rsiQue;

#define _RSI_NODE_WAKEN(pNode) 	((pNode)->waken)

extern 	int  	RSI_InitNode(_t_rsiNode * pNode);
extern 	int  	RSI_InitQue(_t_rsiQue 	* pQue, _t_sysCS * pLock);
extern 	int  	RSI_DeQue(_t_rsiQue 	* pQue, _t_rsiNode * pNode);
extern 	int  	RSI_EnReady(_t_rsiQue * pQue, _t_rsiNode * pNode);
extern 	int  	RSI_EnStdby(_t_rsiQue * pQue, _t_rsiNode * pNode);
extern	int 	RSI_XfStdby(_t_rsiQue * pRSI, int  xfCnt);
extern	int 	RSI_XfReady(_t_rsiQue * pRSI, int  xfCnt, int (*proc)());


/* RSI Command */
extern	int 	SRsi_SetTraceLvl(int lvl);
extern	int 	SRsi_GetTraceLvl(void);

#ifdef __cplusplus
}
#endif

#endif

